﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;

namespace Pavilion
{
    public class CollisionManager
    {
        static private CollisionManager singletonInstance;

        private List<MultiLinePhysicalData> multiLineDataCollection;
        private List<PolygonPhysicalData> polygonDataCollection;

        private List<PolygonAndMultiLineIntersection> polygonAndMultiLineIntersectionList;
        private List<PolygonAndPolygonIntersection> polygonAndPolygonIntersectionList;

        private Dictionary<PolygonPhysicalData, MultiLineCollisionData> polygonToMultiLinesDictionary;
        private Dictionary<MultiLinePhysicalData, PolygonCollisionData> multiLineToPolygonsDictionary;
        private Dictionary<PolygonPhysicalData, PolygonCollisionData> polygonToPolygonsDictaionary;

        public PolygonCollisionData GetPolygonToPolygonsData(PolygonPhysicalData polygonData) { return polygonToPolygonsDictaionary[polygonData]; }
        public MultiLineCollisionData GetPolygonToMultiLinesData(PolygonPhysicalData polygonData) { return polygonToMultiLinesDictionary[polygonData]; }

        private CollisionManager()
        {
            singletonInstance = this;

            multiLineDataCollection = new List<MultiLinePhysicalData>();
            polygonDataCollection = new List<PolygonPhysicalData>();

            polygonAndMultiLineIntersectionList = new List<PolygonAndMultiLineIntersection>();
            polygonAndPolygonIntersectionList = new List<PolygonAndPolygonIntersection>();

            polygonToMultiLinesDictionary = new Dictionary<PolygonPhysicalData, MultiLineCollisionData>();
            multiLineToPolygonsDictionary = new Dictionary<MultiLinePhysicalData, PolygonCollisionData>();
            polygonToPolygonsDictaionary = new Dictionary<PolygonPhysicalData, PolygonCollisionData>();
        }

        static public CollisionManager Instance
        {
            get
            {
                if (singletonInstance == null)
                    new CollisionManager();

                return singletonInstance;
            }
        }

        internal void Update()
        {
            foreach (PolygonAndMultiLineIntersection intersection in polygonAndMultiLineIntersectionList)
                intersection.UpdateIntersection();

            foreach (PolygonAndPolygonIntersection intersection in polygonAndPolygonIntersectionList)
                intersection.UpdateIntersection();

            foreach (MultiLineCollisionData collisionData in polygonToMultiLinesDictionary.Values)
                collisionData.NotifyIntersectionChanged();

            foreach (PolygonCollisionData collisionData in multiLineToPolygonsDictionary.Values)
                collisionData.NotifyIntersectionChanged();

            foreach (PolygonCollisionData collisionData in polygonToPolygonsDictaionary.Values)
                collisionData.NotifyIntersectionChanged();
        }

        public void AddPolygonData(PolygonPhysicalData polygonData, Action<MultiLineCollisionData> polygonAndMultiLineCollisionChangedAction, Action<PolygonCollisionData> polygonAndPolygonCollisionChangedAction)
        {
            polygonToPolygonsDictaionary.Add(polygonData, new PolygonCollisionData(polygonData, polygonAndPolygonCollisionChangedAction));
            polygonToMultiLinesDictionary.Add(polygonData, new MultiLineCollisionData(polygonData, polygonAndMultiLineCollisionChangedAction));
            polygonDataCollection.Add(polygonData);

            foreach(MultiLinePhysicalData multiLineData in multiLineDataCollection)
                polygonAndMultiLineIntersectionList.Add(new PolygonAndMultiLineIntersection(polygonToMultiLinesDictionary[polygonData], multiLineToPolygonsDictionary[multiLineData]));

            foreach (PolygonPhysicalData item in polygonDataCollection)
            {
                if (item != polygonData)
                    polygonAndPolygonIntersectionList.Add(new PolygonAndPolygonIntersection(polygonToPolygonsDictaionary[polygonData], polygonToPolygonsDictaionary[item]));
            }
        }

        public void AddMultiLineData(MultiLinePhysicalData multiLineData, Action<PolygonCollisionData> polygonAndMultiLineCollisionChangedAction)
        {
            multiLineToPolygonsDictionary.Add(multiLineData, new PolygonCollisionData(multiLineData, polygonAndMultiLineCollisionChangedAction));
            multiLineDataCollection.Add(multiLineData);

            foreach (PolygonPhysicalData polygonData in polygonDataCollection)
                polygonAndMultiLineIntersectionList.Add(new PolygonAndMultiLineIntersection(polygonToMultiLinesDictionary[polygonData], multiLineToPolygonsDictionary[multiLineData]));
        }
    }
}
